package org.zoomdev.zoom.dao.impl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zoomdev.zoom.common.caster.Caster;
import org.zoomdev.zoom.dao.DaoException;
import org.zoomdev.zoom.dao.Record;
import org.zoomdev.zoom.dao.driver.SqlDriver;
import org.zoomdev.zoom.dao.modules.CoreDaoModule;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;
import java.util.stream.Collectors;


public final class RecordSqlUtils {


    public static final char QM = '?';  //Question Mark
    public static final char COMMA = ',';  //comma
    public static final Pattern AS_PATTERN = Pattern.compile("([a-z_\\(\\)\\.\\[\\]]+)[\\s]+as[\\s]+([a-z_]+)", Pattern.CASE_INSENSITIVE);
    private static final Logger log = LoggerFactory.getLogger(CoreDaoModule.NAME);


    /**
     * 构建插入语句
     *
     * @param sql
     * @param values
     * @param driver
     * @param table
     * @param record
     */
    public static void buildInsert(StringBuilder sql,
                                   List<Object> values,
                                   SqlDriver driver,
                                   String table,
                                   Record record) {

        sql.append("INSERT INTO ").append(table).append(" (");
        boolean first = true;
        for (Entry<String, Object> entry : record.entrySet()) {
            Object value = entry.getValue();
            String name = entry.getKey();
            if (first) {
                first = false;
            } else {
                sql.append(COMMA);
            }
            values.add(value);
            driver.protectColumn(sql, name);
        }
        sql.append(") VALUES (");
        //?
        join(sql, record.size())
                .append(')');

    }

    /**
     * 问号    组合成  ?,?
     *
     * @param sql
     * @param size 问号个数
     * @return
     */
    public static StringBuilder join(StringBuilder sql, int size) {
        for (int i = 0; i < size; ++i) {
            if (i > 0) {
                sql.append(COMMA);
            }
            sql.append(QM);
        }
        return sql;
    }

    public static void logSql(String sql, List<Object> values) {
        log.info(getSql(sql, values));
    }

    public static String getSql(String sql, List<Object> values) {
        List<Object> printed = values.stream().map(v -> Caster.to(v, String.class)).collect(Collectors.toList());
        Object[] args = printed.toArray(new Object[printed.size()]);
        return String.format(sql
                .replace("%", "%%")
                .replace("?", "'%s'"), args);
    }

    public static void logSql(String sql) {
        log.info(sql);
    }

    public static void buildUpdate(
            StringBuilder sql,
            List<Object> values,
            SqlDriver driver,
            String table,
            StringBuilder where,
            Record record,
            Map<String, Object> raw
    ) {
        sql.append("UPDATE ").append(table);
        boolean first = true;
        int index = 0;
        for (Entry<String, Object> entry : record.entrySet()) {
            Object value = entry.getValue();
            if (first) {
                first = false;
                sql.append(" SET ");
            } else {
                sql.append(COMMA);
            }
            values.add(index++, value);
            driver.protectColumn(sql, entry.getKey()).append("=?");
        }

        if (raw != null) {
            first = true;
            index = 0;
            for (Entry<String, Object> entry : raw.entrySet()) {
                Object value = entry.getValue();
                if (first) {
                    first = false;
                    sql.append(" SET ");
                } else {
                    sql.append(COMMA);
                }
                values.add(index++, value);
                sql.append(entry.getKey());
            }

        }

        if (where.length() > 0) {
            sql.append(" WHERE ").append(where);
        }

    }

    /**
     * 构建delete语句
     */
    public static void buildDelete(
            StringBuilder sql,
            String table,
            StringBuilder where
    ) {
        if (where.length() <= 0) {
            throw new DaoException("Whole table delete is not valid!");
        }
        sql.append("DELETE FROM ").append(table);
        if (where.length() > 0) {
            sql.append(" WHERE ").append(where);
        }
    }


}
